﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CustomAuthorizationDemo.Authentication;
using CustomAuthorizationDemo.Authorization;
using CustomAuthorizationDemo.DTO;
using CustomAuthorizationDemo.Security.Session;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace CustomAuthorizationDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [AuthorizationFilter]
    public class AuthController : ControllerBase
    {
        private readonly IAuthenticationService authService;
        private readonly IClaimsSession Session;

        public AuthController(IAuthenticationService authService, IClaimsSession session)
        {
            this.authService = authService ?? throw new ArgumentNullException(nameof(authService));
            this.Session = session;
        }

        /// <summary>
        /// 登录系统
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [Route("[action]")]
        [ProducesResponseType(typeof(Identity), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public IActionResult Login(LoginInput input)
        {
            IIdentity identity;
            try
            {
                identity = authService.Login(input.UserName, input.Password);
            }
            /*catch (UserNotFoundException)
            {
                return new LoginResult(LoginResultType.InvalidUserName, "无效的用户名");
            }
            catch (PasswordInvalidException)
            {
                return new LoginResult(LoginResultType.InvalidPassword, "密码错误，请重试！");
            }*/
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
            if (identity == null)
                return Unauthorized("登录失败！请检查用户名及密码是否正确。");
            if(Session.UserId.HasValue)
                authService.Logout();
            return Ok(identity);
        }

        /// <summary>
        /// 登出系统
        /// </summary>
        [ApiAuthorize]
        [HttpPost]
        [Route("[action]")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public IActionResult Logout()
        {
            if (!Session.UserId.HasValue)
                return Unauthorized();
            authService.Logout();
            return Ok();
        }

        /// <summary>
        /// 请求刷新令牌
        /// </summary>
        /// <param name="token">刷新令牌</param>
        /// <returns></returns>
        [ApiAuthorize]
        [HttpPost]
        [Route("[action]")]
        [ProducesResponseType(typeof(IToken), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public IActionResult Refresh(string token)
        {
            if (!Session.UserId.HasValue)
                return Unauthorized();
            IToken tk;
            try
            {
                tk = authService.RefreshToken(token);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
            return Ok(tk);
        }

        /// <summary>
        /// 验证令牌是否有效，有效则返回登录信息
        /// </summary>
        /// <param name="token">访问令牌</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet]
        [Route("[action]")]
        [ProducesResponseType(typeof(Identity), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
        public IActionResult Validate(string token)
        {
            IIdentity identity;
            try
            {
                identity = authService.ValidateToken(token);
            }
            catch (Exception ex)
            {
                return Conflict(ex.Message);
            }
            if (identity == null)
            {
                return BadRequest();
            }
            return Ok(identity);
        }

    }
}